#include "finite_state_machine.h"

void finite_state_machine_t::operator()(uchar ch)
{
    switch (state)
    {
    case STATE_DATA:
        switch (ch)
        {
        case IAC:
            state = STATE_IAC;
            break;
        default: //DATA
            process_data(ch);
            break;
        }
        break;
    case STATE_IAC:
        switch (ch)
        {
        case IAC:
            state = STATE_DATA;
            break;
        case DO:
            verb = VERB_DO;
            state = STATE_OPTION;
            break;
        case DONT:
            verb = VERB_DONT;
            state = STATE_OPTION;
            break;
        case WILL:
            verb = VERB_WILL;
            state = STATE_OPTION;
            break;
        case WONT:
            verb = VERB_WONT;
            state = STATE_OPTION;
            break;
        case SB:
            state = STATE_SUBOPTION;
            break;
        case SE:
            state = STATE_SUBOPTION;
        default:
            state = STATE_DATA;
            break;
        }
        break;
    case STATE_OPTION:
        state = STATE_DATA;
        switch (ch)
        {
        case ECHO:
            deal_ECHO(verb);
            break;
        case SGA:
            deal_SGA(verb);
            break;
        case TERMTYPE:
            deal_TERMTYPE(verb);
            break;
        case NAWS:
            deal_NAWS(verb);
            break;
        case TSPEED:
            deal_TSPEED(verb);
            break;
        case LFLOW:
            deal_LFLOW(verb);
            break;
        case LINEMODE:
            deal_LINEMODE(verb);
            break;
        case ENVIRON:
            deal_ENVIRON(verb);
            break;
        case STATUS:
            deal_STATUS(verb);
            break;
        }

        switch (verb)
        {
        case VERB_DO:
            send_pass(if_support[ch] ? WILL : WONT, ch);
            break;
        case VERB_DONT:
            send_pass(WONT, ch);
            break;
        case VERB_WILL:
            send_pass(if_support[ch] ? DO : DONT, ch);
            break;
        case VERB_WONT:
            send_pass(DONT, ch);
            break;
        }
        break;
    case STATE_SUBOPTION:
        switch (ch)
        {
        case TERMTYPE:
            send_term_type();
            break;
        default:
            break;
        }
        break;
    }
}
